home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 351-375 / disk_354 / keymacro / keymacro.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  15KB  |  802 lines

  1. /****************************************************************************
  2. *
  3. *    KeyMacro.c ------------    KeyMacro main process.
  4. *
  5. *    Author ----------------    Olaf Barthel, MXM
  6. *                Brabeckstrasse 35
  7. *                D-3000 Hannover 71
  8. *
  9. *    KeyMacro  ©  Copyright  1990  by  MXM;  Executable  program,
  10. *    documentation  and  source  code are shareware.  If you like
  11. *    this  program  a  small donation will entitle you to receive
  12. *    updates and new programs from MXM.
  13. *
  14. ****************************************************************************/
  15.  
  16. #include <libraries/arpbase.h>
  17.  
  18.     /* Function prototypes. */
  19.  
  20. VOID *            SendMacroMsg(struct MacroMessage *);
  21. UBYTE *            GetToken(UBYTE *,LONG *);
  22. struct MacroKey *    AddMacroKey(struct MacroKey *);
  23. LONG            Interprete(UBYTE *,LONG);
  24. LONG            UpdateList(char *);
  25.  
  26. VOID            main(LONG,char **);
  27.  
  28.     /* The Arp CLI-Interface data. */
  29.  
  30. char *CLI_Template    = "STARTUP/K,QUIT/S,INFO/S";
  31. char *CLI_Help        = "\nUsage: \33[1mKeyMacro\33[0m [STARTUP <File>] [QUIT] [INFO]\n";
  32.  
  33. #define ARG_STARTUP    1
  34. #define ARG_QUIT    2
  35. #define ARG_INFO    3
  36. #define ARG_UPDATE    4
  37.  
  38.     /* Easy macro. */
  39.  
  40. #define From_CLI    (ThatsMe -> pr_CLI)
  41.  
  42.     /* Global and shared data structures. */
  43.  
  44. struct MXMBase        *MXMBase;
  45. extern struct ArpBase    *ArpBase;
  46. struct MSeg        *MSeg;
  47. struct MacroKey        *KeyList;
  48. extern struct ExecBase    *SysBase;
  49.  
  50.     /* We use this list to identify the non-ascii keys. */
  51.  
  52. struct KeyAlias KeyTab[22] =
  53. {
  54.     {"TAB",        0x42},
  55.     {"ESC",        0x45},
  56.     {"SPACE",    0x40},
  57.     {"RETURN",    0x44},
  58.     {"ENTER",    0x43},
  59.     {"DEL",        0x46},
  60.     {"BACKSPACE",    0x41},
  61.     {"HELP",    0x5F},
  62.     {"LEFT",    0x4F},
  63.     {"RIGHT",    0x4E},
  64.     {"UP",        0x4C},
  65.     {"DOWN",    0x4D},
  66.  
  67.     {"F1",        0x50},
  68.     {"F2",        0x51},
  69.     {"F3",        0x52},
  70.     {"F4",        0x53},
  71.     {"F5",        0x54},
  72.     {"F6",        0x55},
  73.     {"F7",        0x56},
  74.     {"F8",        0x57},
  75.     {"F9",        0x58},
  76.     {"F10",        0x59}
  77. };
  78.  
  79.     /* These are the qualifiers. */
  80.  
  81. struct KeyAlias QualifierTab[9] =
  82. {
  83.     {"NONE",    0},
  84.     {"CTRL",    IEQUALIFIER_CONTROL},
  85.     {"NUMPAD",    IEQUALIFIER_NUMERICPAD},
  86.     {"LSHIFT",    IEQUALIFIER_LSHIFT},
  87.     {"RSHIFT",    IEQUALIFIER_RSHIFT},
  88.     {"LALT",    IEQUALIFIER_LALT},
  89.     {"RALT",    IEQUALIFIER_RALT},
  90.     {"LAMIGA",    IEQUALIFIER_LCOMMAND},
  91.     {"RAMIGA",    IEQUALIFIER_RCOMMAND}
  92. };
  93.  
  94.     /* SendMacroMsg(scm_Msg,scm_Port):
  95.      *
  96.      *    Post a cloned macro message to a MsgPort.
  97.      */
  98.  
  99. VOID *
  100. SendMacroMsg(struct MacroMessage *scm_Msg)
  101. {
  102.     struct MacroMessage *scm_TempMsg = (struct MacroMessage *)AllocRem(sizeof(struct MacroMessage),MEMF_PUBLIC | MEMF_CLEAR);
  103.  
  104.     if(scm_TempMsg)
  105.     {
  106.         CopyMem(scm_Msg,scm_TempMsg,sizeof(struct MacroMessage));
  107.  
  108.         scm_TempMsg -> mm_Message . mn_Node . ln_Name    = (char *)scm_TempMsg;
  109.         scm_TempMsg -> mm_Message . mn_ReplyPort    = NULL;
  110.         scm_TempMsg -> mm_Message . mn_Length        = sizeof(struct MacroMessage);
  111.  
  112.         PutMsg(&MSeg -> Port,(struct Message *)scm_TempMsg);
  113.     }
  114.  
  115.     return((VOID *)scm_TempMsg);
  116. }
  117.  
  118.     /* GetToken(s,start):
  119.      *
  120.      *    Parse a string and split it into single tokens.
  121.      */
  122.  
  123. UBYTE *
  124. GetToken(UBYTE *s,LONG *start)
  125. {
  126.     static UBYTE buffer[256];
  127.     LONG i,end = 0,quote = FALSE,maxlen = strlen(s);
  128.     char t;
  129.  
  130.     if(maxlen > 255)
  131.         maxlen = 255;
  132.  
  133.     if(*start > strlen(s) - 1 || !strlen(s) || !s)
  134.         return(NULL);
  135.  
  136.     for(i = *start ; i <= maxlen ; i++)
  137.     {
  138.         if(!end && (s[i] == ' ' || s[i] == '\t'))
  139.         {
  140.             while((s[i] == ' ' || s[i] == '\t') && i < maxlen)
  141.             {
  142.                 i++;
  143.                 (*start)++;
  144.             }
  145.         }
  146.  
  147.         t = s[i];
  148.  
  149.         if(!end && t == '+')
  150.         {
  151.             (*start)++;
  152.             continue;
  153.         }
  154.  
  155.         if(!end && t == '=')
  156.         {
  157.             strcpy(buffer,"=");
  158.             (*start)++;
  159.  
  160.             return(buffer);
  161.         }
  162.  
  163.         if(s[i] == '\\' && s[i + 1] == '\"')
  164.         {
  165.             i += 2;
  166.  
  167.             end = i - *start + 1;
  168.  
  169.             t = s[i];
  170.         }
  171.  
  172.         if(t == '\"' && !quote)
  173.         {
  174.             quote = TRUE;
  175.  
  176.             (*start)++;
  177.  
  178.             end++;
  179.  
  180.             continue;
  181.         }
  182.  
  183.         if((t == '+' || t == '=' || t == ' ' || t == '\t' || t == ';') && quote)
  184.         {
  185.             end++;
  186.             continue;
  187.         }
  188.  
  189.         if((t == '+' || t == '\n' || t == '=' || t == ' ' || t == 0) || (t == '\"' && quote) || (t == ';' && !quote))
  190.         {
  191.             if(t == ';' && !end)
  192.                 return(NULL);
  193.  
  194.             if(t == '\"')
  195.             {
  196.                 strncpy(buffer,s + *start,end - 1);
  197.                 buffer[end - 1] = 0;
  198.             }
  199.             else
  200.             {
  201.                 strncpy(buffer,s + *start,end);
  202.                 buffer[end] = 0;
  203.             }
  204.  
  205.             (*start) += end;
  206.  
  207.             return(buffer);
  208.         }
  209.  
  210.         end++;
  211.     }
  212.  
  213.     return(NULL);
  214. }
  215.  
  216.     /* AddMacroKey(MacroKey):
  217.      *
  218.      *    Add a macro key to the big list.
  219.      */
  220.  
  221. struct MacroKey *
  222. AddMacroKey(struct MacroKey *MacroKey)
  223. {
  224.     struct MacroKey *TheKey = NULL;
  225.     LONG i;
  226.  
  227.     for(i = 0 ; i < MSeg -> NumMacros ; i++)
  228.     {
  229.         if(KeyList[i] . mk_Type == MK_UNUSED)
  230.         {
  231.             TheKey = &KeyList[i];
  232.             break;
  233.         }
  234.     }
  235.  
  236.     if(!TheKey)
  237.         return(NULL);
  238.  
  239.     CopyMem(MacroKey,TheKey,sizeof(struct MacroKey));
  240.  
  241.     return(TheKey);
  242. }
  243.  
  244.     /* Interprete(String,Line):
  245.      *
  246.      *    Interprete a command line from the config file.
  247.      */
  248.  
  249. LONG
  250. Interprete(UBYTE *String,LONG Line)
  251. {
  252.     ULONG Qualifier = 0;
  253.     ULONG Code = -1;
  254.     struct InputEvent FakeEvent;
  255.     struct MacroKey NewKey;
  256.  
  257.     LONG Start = 0,Key = FALSE,i,KeyCount = 0;
  258.     volatile LONG QuitLoop;
  259.     UBYTE *Token,*CommandString,*WindowName = NULL,Recognized = FALSE;
  260.  
  261.     UBYTE MessBuff[256],KeyBuff1[40],KeyBuff2[40];
  262.  
  263.     if(String[strlen(String) - 1] == '\n')
  264.         String[strlen(String) - 1] = 0;
  265.  
  266.     if(Token = GetToken(String,&Start))
  267.     {
  268.         if(!UStrCmp("KEY",Token))
  269.             Key = TRUE;
  270.  
  271.         if(UStrCmp("COMMAND",Token) && !Key)
  272.         {
  273.             SPrintf(MessBuff,"Line %ld: Unknown keyword:\n\n'%s'",Line,String);
  274.  
  275.             PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE,NULL);
  276.             return(FALSE);
  277.         }
  278.     }
  279.     else
  280.         return(TRUE);
  281.  
  282.     FOREVER
  283.     {
  284.         if(Token = GetToken(String,&Start))
  285.         {
  286.             QuitLoop = TRUE;
  287.  
  288.             for(i = 0 ; i < 9 ; i++)
  289.             {
  290.                 if(!UStrCmp(QualifierTab[i] . ka_Name,Token))
  291.                 {
  292.                     Recognized = TRUE;
  293.                     QuitLoop = FALSE;
  294.  
  295.                     Qualifier |= QualifierTab[i] . ka_Key;
  296.                 }
  297.             }
  298.         }
  299.         else
  300.             break;
  301.  
  302.         if(QuitLoop)
  303.             break;
  304.     }
  305.  
  306.     if(!Recognized)
  307.     {
  308.         SPrintf(MessBuff,"Line %ld: Didn't recognize qualifier:\n\n'%s'",Line,String);
  309.  
  310.         PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE,NULL);
  311.         return(FALSE);
  312.     }
  313.  
  314.     if(Token)
  315.         goto JumpIn;
  316.  
  317.     if(Token = GetToken(String,&Start))
  318.     {
  319. JumpIn:        for(i = 0 ; i < 22 ; i++)
  320.         {
  321.             if(!UStrCmp(KeyTab[i] . ka_Name,Token))
  322.             {
  323.                 Code = KeyTab[i] . ka_Key;
  324.                 goto Next;
  325.             }
  326.         }
  327.  
  328.         if(InvertKey(Token[0],&FakeEvent,IK_USEIKM,NULL))
  329.             Code = FakeEvent . ie_Code;
  330.     }
  331.  
  332.     if(Code == -1)
  333.     {
  334.         SPrintf(MessBuff,"Line %ld: Didn't recognize key:\n\n'%s'",Line,String);
  335.  
  336.         PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE,NULL);
  337.         return(FALSE);
  338.     }
  339.  
  340. Next:    FOREVER
  341.     {
  342.         if(Token = GetToken(String,&Start))
  343.         {
  344.             if(!UStrCmp("=",Token))
  345.                 break;
  346.         }
  347.         else
  348.         {
  349.             SPrintf(MessBuff,"Line %ld: Statement '=' missing:\n\n'%s'",Line,String);
  350.  
  351.             PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE,NULL);
  352.             return(FALSE);
  353.         }
  354.     }
  355.  
  356.     if(Token = GetToken(String,&Start))
  357.         strcpy(KeyBuff1,Token);
  358.     else
  359.     {
  360.         SPrintf(MessBuff,"Line %ld: Didn't find macro:\n\n'%s'",Line,String);
  361.  
  362.         PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE,NULL);
  363.         return(FALSE);
  364.     }
  365.  
  366.     if(Key)
  367.         goto AddIt;
  368.  
  369.     if(!(Token = GetToken(String,&Start)))
  370.         goto AddIt;
  371.  
  372.     if(UStrCmp("WINDOW",Token))
  373.     {
  374.         SPrintf(MessBuff,"Line %ld: Didn't recognize 'WINDOW' statement:\n\n'%s'",Line,String);
  375.  
  376.         PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE,NULL);
  377.         return(FALSE);
  378.     }
  379.  
  380.     if(!(Token = GetToken(String,&Start)))
  381.     {
  382.         SPrintf(MessBuff,"Line %ld: Didn't find window title:\n\n'%s'",Line,String);
  383.  
  384.         PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE,NULL);
  385.         return(FALSE);
  386.     }
  387.  
  388.     if(!(WindowName = (UBYTE *)AllocRem(strlen(Token) + 1,MEMF_PUBLIC)))
  389.     {
  390.         PopRequest(NULL,"KeyMacro Problem:","Can't allocate memory chunk!",NULL,"Continue?",FALSE,NULL);
  391.         return(FALSE);
  392.     }
  393.  
  394.     strcpy(WindowName,Token);
  395.  
  396. AddIt:    for(i = 0 ; i < strlen(KeyBuff1) ; i++)
  397.     {
  398.         UBYTE c;
  399.  
  400.         if(KeyBuff1[i] != '\\')
  401.         {
  402.             KeyBuff2[KeyCount++] = KeyBuff1[i];
  403.             continue;
  404.         }
  405.  
  406.         if(i == strlen(KeyBuff1) - 1)
  407.             break;
  408.  
  409.         i++;
  410.  
  411.         c = 0;
  412.  
  413.         switch(ToUpper(KeyBuff1[i]))
  414.         {
  415.             case 'U':    c = KC_CURSORUP;
  416.                     break;
  417.  
  418.             case 'D':    c = KC_CURSORDOWN;
  419.                     break;
  420.  
  421.             case 'L':    c = KC_CURSORLEFT;
  422.                     break;
  423.  
  424.             case 'R':    c = KC_CURSORRIGHT;
  425.                     break;
  426.  
  427.             case 'H':    c = KC_HELP;
  428.                     break;
  429.  
  430.             case 'B':    c = 8;
  431.                     break;
  432.  
  433.             case 'E':    c = 127;
  434.                     break;
  435.  
  436.             case 'F':    if(i == strlen(KeyBuff1) - 1)
  437.                         break;
  438.  
  439.                     i++;
  440.  
  441.                     if(!isdigit(KeyBuff1[i]))
  442.                         break;
  443.  
  444.                     if(!KeyBuff1[i] == '1')
  445.                     {
  446.                         c = KC_FKEY1 + KeyBuff1[i] - '1';
  447.                         break;
  448.                     }
  449.  
  450.                     if(i == strlen(KeyBuff1) - 1)
  451.                         break;
  452.  
  453.                     i++;
  454.  
  455.                     if(!isdigit(KeyBuff1[i]))
  456.                     {
  457.                         c = KC_FKEY1;
  458.                         break;
  459.                     }
  460.  
  461.                     if(KeyBuff1[i] != '0')
  462.                         break;
  463.  
  464.                     c = KC_FKEY10;
  465.                     break;
  466.  
  467.             case 'N':    c = '\n';
  468.                     break;
  469.  
  470.             case '\\':    c = '\\';
  471.                     break;
  472.  
  473.             default:    c = KeyBuff1[i];
  474.  
  475.                     break;
  476.         }
  477.  
  478.         if(c)
  479.             KeyBuff2[KeyCount++] = c;
  480.     }
  481.  
  482.     KeyBuff2[KeyCount] = 0;
  483.  
  484.     if(!(CommandString = (UBYTE *)AllocRem(strlen(KeyBuff2) + 1,MEMF_PUBLIC)))
  485.     {
  486.         PopRequest(NULL,"KeyMacro Problem:","Can't allocate memory chunk!",NULL,"Continue?",FALSE,NULL);
  487.         FreeRem(WindowName);
  488.  
  489.         return(FALSE);
  490.     }
  491.  
  492.     strcpy(CommandString,KeyBuff2);
  493.  
  494.     memset(&NewKey,0,sizeof(struct MacroKey));
  495.  
  496.     NewKey . mk_CommandKey        = Code;
  497.     NewKey . mk_CommandQualifier    = Qualifier;
  498.  
  499.     NewKey . mk_String        = CommandString;
  500.     NewKey . mk_Window        = WindowName;
  501.  
  502.     if(Key)
  503.         NewKey . mk_Type    = MK_WORD;
  504.     else
  505.         NewKey . mk_Type    = MK_COMMAND;
  506.  
  507.     if(AddMacroKey(&NewKey))
  508.         return(TRUE);
  509.  
  510.     SPrintf(MessBuff,"Line %ld: Key macro table full.",Line);
  511.  
  512.     PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE,NULL);
  513.     return(FALSE);
  514. }
  515.  
  516.     /* UpdateList(Name):
  517.      *
  518.      *    Update the big macro key list.
  519.      */
  520.  
  521. LONG
  522. UpdateList(char *Name)
  523. {
  524.     char LineBuff[256];
  525.     LONG LineNum = 1;
  526.     FILE *ConfigFile;
  527.  
  528.     if(!Name)
  529.         Name = "S:KeyMacro.config";
  530.  
  531.     if(!(KeyList = (struct MacroKey *)AllocRem(sizeof(struct MacroKey) * MAXMACROS,MEMF_PUBLIC | MEMF_CLEAR)))
  532.     {
  533.         PopRequest(NULL,"KeyMacro Problem:","Can't allocate memory chunk!",NULL,"Continue?",FALSE,NULL);
  534.         return(FALSE);
  535.     }
  536.  
  537.     MSeg -> NumMacros = MAXMACROS;
  538.  
  539.     if(ConfigFile = fopen(Name,"r"))
  540.     {
  541.         while(fgets(LineBuff,256,ConfigFile))
  542.         {
  543.             if(!Interprete(LineBuff,LineNum++))
  544.             {
  545.                 fclose(ConfigFile);
  546.  
  547.                 FreeRem(KeyList);
  548.  
  549.                 return(FALSE);
  550.             }
  551.         }
  552.  
  553.         fclose(ConfigFile);
  554.     }
  555.     else
  556.     {
  557.         PopRequest(NULL,"KeyMacro Problem:","Couldn't open configuration file!",NULL,"Continue?",FALSE,NULL);
  558.         return(FALSE);
  559.     }
  560.  
  561.     return(TRUE);
  562. }
  563.  
  564.     /* main(argc,argv):
  565.      *
  566.      *    The entry point to this program.
  567.      */
  568.  
  569. VOID
  570. main(LONG argc,char **argv)
  571. {
  572.     struct Process *ThatsMe = (struct Process *)SysBase -> ThisTask;
  573.     LONG Created = FALSE;
  574.     char *FileName = argv[ARG_STARTUP];
  575.     LONG i;
  576.  
  577.         /* No ^C trapping, please. */
  578.  
  579.     Enable_Abort = FALSE;
  580.  
  581.         /* Started from Workbench? */
  582.  
  583.     if(!From_CLI)
  584.         FileName = NULL;
  585.  
  586.         /* Try to open mxm.library. */
  587.  
  588.     if(!(MXMBase = (struct MXMBase *)OpenLibrary("mxm.library",34)))
  589.     {
  590.         if(From_CLI)
  591.             Puts("\33[1mKeyMacro:\33[0m You need \33[1mmxm.library\33[0m 34.12 or higher to run this program.");
  592.  
  593.         exit(RETURN_FAIL);
  594.     }
  595.  
  596.         /* Look if handler process is already running. */
  597.  
  598.     MSeg = (struct MSeg *)FindPort(PORTNAME);
  599.  
  600.         /* Short info? */
  601.  
  602.     if(argv[ARG_INFO])
  603.     {
  604.         Printf("\n\33[1m\33[33mKeyMacro\33[31m\33[0m the Amiga macro key handler.\n\n");
  605.  
  606.         Printf("         This program may be non-commercially\n");
  607.         Printf("         redistributed!\n\n");
  608.  
  609.         Printf("\33[1m\33[33mAuthor\33[31m\33[0m - Olaf Barthel, MXM\n");
  610.         Printf("         Brabeckstrasse 35\n");
  611.         Printf("         D-3000 Hannover 71\n\n");
  612.  
  613.         Printf("     Federal Republic of Germany.\n\n");
  614.  
  615.         CloseLibrary((struct Library *)MXMBase);
  616.  
  617.         exit(RETURN_OK);
  618.     }
  619.  
  620.         /* Remove the handler? */
  621.  
  622.     if(argv[ARG_QUIT])
  623.     {
  624.         Printf("Removing \33[1m\33[33mKeyMacro\33[31m\33[0m, ");
  625.  
  626.         if(!MSeg)
  627.         {
  628.             Printf("failed!\7\n");
  629.  
  630.             CloseLibrary((struct Library *)MXMBase);
  631.  
  632.             exit(RETURN_OK);
  633.         }
  634.  
  635.         MSeg -> Father = (struct Task *)SysBase -> ThisTask;
  636.  
  637.         if(MSeg -> Child)
  638.         {
  639.             Signal(MSeg -> Child,SIG_CLOSE);
  640.             Wait(SIG_CLOSE);
  641.         }
  642.  
  643.         RemPort((struct MsgPort *)MSeg);
  644.         FreeMem(MSeg -> Port . mp_Node . ln_Name,sizeof(PORTNAME));
  645.  
  646.         if(MSeg -> Segment)
  647.             UnLoadPrg(MSeg -> Segment);
  648.  
  649.         if(MSeg -> MacroList)
  650.         {
  651.             for(i = 0 ; i < MSeg -> NumMacros ; i++)
  652.             {
  653.                 if(MSeg -> MacroList[i] . mk_Type == MK_UNUSED)
  654.                     continue;
  655.  
  656.                 if(MSeg -> MacroList[i] . mk_String)
  657.                     FreeRem(MSeg -> MacroList[i] . mk_String);
  658.  
  659.                 if(MSeg -> MacroList[i] . mk_Window)
  660.                     FreeRem(MSeg -> MacroList[i] . mk_Window);
  661.             }
  662.  
  663.             FreeRem(MSeg -> MacroList);
  664.         }
  665.  
  666.         FreeRem(MSeg);
  667.  
  668.         Printf("OK.\n");
  669.  
  670.         CloseLibrary((struct Library *)MXMBase);
  671.  
  672.         exit(RETURN_OK);
  673.     }
  674.  
  675.         /* Allocate the handler data. */
  676.  
  677.     if(!MSeg)
  678.     {
  679.         if(MSeg = (struct MSeg *)AllocRem(sizeof(struct MSeg),MEMF_PUBLIC | MEMF_CLEAR))
  680.         {
  681.             MSeg -> Port . mp_Flags            = PA_IGNORE;
  682.             MSeg -> Port . mp_Node . ln_Pri        = 0;
  683.             MSeg -> Port . mp_Node . ln_Type    = NT_MSGPORT;
  684.             MSeg -> Port . mp_Node . ln_Name    = AllocMem(sizeof(PORTNAME),MEMF_PUBLIC);
  685.             MSeg -> Child                = NULL;
  686.             MSeg -> Father                = (struct Task *)SysBase -> ThisTask;
  687.             MSeg -> SegSize                = sizeof(struct MSeg);
  688.             MSeg -> RingBack            = SIGBREAKF_CTRL_C;
  689.             MSeg -> Revision            = REVISION;
  690.  
  691.             NewList(&MSeg -> Port . mp_MsgList);
  692.  
  693.             if(From_CLI)
  694.             {
  695.                 Printf("\33[1m\33[33mKeyMacro v1.%ld \33[31m\33[0m(C) Copyright 1989, 1990 by \33[4mMXM\33[0m.\n",REVISION);
  696.  
  697.                 Printf("Installing \33[33m\33[1mKeyMacro\33[0m\33[31m, ");
  698.             }
  699.  
  700.             if(MSeg -> Port . mp_Node . ln_Name)
  701.                 strcpy(MSeg -> Port . mp_Node . ln_Name,PORTNAME);
  702.             else
  703.             {
  704.                 if(From_CLI)
  705.                     Printf("failed!\n");
  706.  
  707.                 CloseLibrary((struct Library *)MXMBase);
  708.  
  709.                 exit(RETURN_FAIL);
  710.             }
  711.  
  712.             MSeg -> Segment = LoadPrg("KeyMacro-Handler");
  713.  
  714.             if(!MSeg -> Segment)
  715.                 MSeg -> Segment = LoadPrg("L:KeyMacro-Handler");
  716.  
  717.             if(!MSeg -> Segment)
  718.             {
  719.                 if(From_CLI)
  720.                     Printf("unable to find \33[33mL:KeyMacro-Handler\33[31m\7!\n");
  721.  
  722.                 FreeRem(MSeg -> Port . mp_Node . ln_Name);
  723.                 FreeRem(MSeg);
  724.             }
  725.             else
  726.             {
  727.                 AddPort((struct MsgPort *)MSeg);
  728.  
  729.                 if(!CreateProc("KeyMacro-Handler",10,MSeg -> Segment,4096))
  730.                     goto NoMem;
  731.  
  732.                 Wait(SIGBREAKF_CTRL_C);
  733.  
  734.                 if(!MSeg -> Child)
  735.                 {
  736. NoMem:                    if(From_CLI)
  737.                         Printf("\33[33mFAILED!\33[31m (care to retry?)\n");
  738.  
  739.                     RemPort((struct MsgPort *)MSeg);
  740.                     FreeRem(MSeg -> Port . mp_Node . ln_Name);
  741.  
  742.                     if(MSeg -> Segment)
  743.                         UnLoadPrg(MSeg -> Segment);
  744.  
  745.                     FreeRem(MSeg);
  746.  
  747.                     CloseLibrary((struct Library *)MXMBase);
  748.  
  749.                     exit(RETURN_FAIL);
  750.                 }
  751.                 else
  752.                 {
  753.                     if(From_CLI)
  754.                         Printf("initializing, ");
  755.  
  756.                     InvertKey(NULL,NULL,IK_USEIKM | IK_BUILDLIST,NULL);
  757.  
  758.                     if(From_CLI)
  759.                         Puts("Okay.");
  760.                     else
  761.                         PopRequest(NULL,"KeyMacro Info:","\33[1mKeyMacro\33[0m installed.",NULL,"Continue?",FALSE,NULL);
  762.  
  763.                     Created = TRUE;
  764.                 }
  765.             }
  766.         }
  767.     }
  768.  
  769.         /* Update the macro key list. */
  770.  
  771.     if(UpdateList(FileName))
  772.     {
  773.         if(Created)
  774.         {
  775.             MSeg -> NumMacros = MAXMACROS;
  776.             MSeg -> MacroList = KeyList;
  777.         }
  778.         else
  779.         {
  780.             struct MacroMessage UpdateMsg;
  781.  
  782.             UpdateMsg . mm_Type    = MM_UPDATE;
  783.             UpdateMsg . mm_NumMacros= MAXMACROS;
  784.             UpdateMsg . mm_MacroList= KeyList;
  785.  
  786.             SendMacroMsg(&UpdateMsg);
  787.  
  788.             if(From_CLI)
  789.                 Printf("\33[1mKeyMacro:\33[0m Updating macro keys...\n");
  790.         }
  791.     }
  792.     else
  793.     {
  794.         CloseLibrary((struct Library *)MXMBase);
  795.         exit(RETURN_ERROR);
  796.     }
  797.  
  798.     CloseLibrary((struct Library *)MXMBase);
  799.  
  800.     exit(RETURN_OK);
  801. }
  802.